package com.zhx.common.common.aspect;


import cn.hutool.core.date.StopWatch;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.zhx.common.common.domain.dto.RequestInfo;
import com.zhx.common.common.util.RequestHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Component
@Aspect
@Slf4j
public class WebLogAspect {
    @Around("execution(* com..controller..*.*(..))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //这个Java函数的功能是获取当前的HttpServletRequest对象。
        //首先，通过RequestContextHolder.getRequestAttributes()方法获取当前的请求属性。
        //然后，使用Objects.requireNonNull()方法确保请求属性不为空。
        //最后，通过请求属性获取当前的HttpServletRequest对象。
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        //如果参数有HttpRequest，ServletResponse，直接移除不打印这些
        List<Object> paramList = Stream.of(proceedingJoinPoint.getArgs())
                .filter(args -> !(args instanceof ServletRequest))
                .filter(args -> !(args instanceof ServletResponse))
                .collect(Collectors.toList());

        String printParamStr = paramList.size() == 1 ? JSONUtil.toJsonStr(paramList.get(0)) : JSONUtil.toJsonStr(paramList);
        RequestInfo requestInfo = RequestHolder.get();
        String userHeaderStr = JSONUtil.toJsonStr(requestInfo);
        if(log.isInfoEnabled()){
            log.info("[{}][{}]【base:{}】【request:{}】",method,uri,userHeaderStr,printParamStr);
        }

        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        //执行方法
        Object result = proceedingJoinPoint.proceed();
        stopWatch.stop();
        //方法/接口执行时长
        long cost = stopWatch.getTotalTimeMillis();
        String printResultStr = JSONUtil.toJsonStr(result);
        if (log.isInfoEnabled()) {
            log.info("[{}]【response:{}】[cost:{}ms]", uri, printResultStr, cost);
        }

        return result;
    }
}
